package fox.framework.rpc.context;

import fox.framework.rpc.client.invocation.ConsumeInvoker;
import fox.framework.rpc.client.message.RpcClientRequestInterceptor;
import fox.framework.rpc.context.order.Order;
import fox.framework.rpc.context.aware.*;
import fox.framework.rpc.context.definition.RpcDefinition;
import fox.framework.rpc.context.event.*;
import fox.framework.rpc.context.processor.RpcDefinitionRegisterProcessor;
import fox.framework.rpc.context.processor.RpcApplicationProcessor;
import fox.framework.rpc.server.dispatcher.invoke.ProvideInvoker;
import fox.framework.rpc.server.dispatcher.router.RpcRouter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author cuiochao
 * Rpc-Client抽象基础类
 */
public abstract class AbstractRpcApplicationContext extends ConfigurableRpcApplicationContext {

    protected final List<RpcDefinition> definitions = Collections.synchronizedList(new ArrayList<>());
    /**
     * 事件发布器
     */
    private RpcEventMulticaster multicaster = new DefaultRpcEventMulticaster();
    /**
     * 客户端方法执行器
     */
    private List<ConsumeInvoker> registeredConsumeInvoke = new ArrayList<>();
    /**
     * 事件处理器列表
     */
    private List<RpcApplicationProcessor> registeredProcessors = new ArrayList<>();


    @Override
    protected RpcEventPublisher getRpcEventPublisher() {
        return this;
    }

    @Override
    public void publishEvent(RpcEvent event) {
        multicaster.publishEvent(event);
    }


    @Override
    public void run() throws Exception {
        //启动前准备
        prepareRefresh();
        //执行RpcApplicationProcessor
        invokeRpcApplicationProcessor(this);
        //刷新容器工厂
        refreshObjectFactory();
        //生成Rpc服务注册表
        refreshRpcDefinition();
        //生成RpcRouter列表
        refreshRpcRouter(getDefinitions());
        //启动Rpc-Client
        enableRpcClient(getDefinitions());
    }

    @Override
    public void shutdown() throws Exception {

    }

    /**
     * 创建rpcRouter
     */
    private void refreshRpcRouter(List<RpcDefinition> definitions) {
        RpcRouter router = getRouter();
        router.clear();
        for (RpcDefinition definition : definitions) {
            if (definition.isProvider()) {
                router.addMapping(getObjectFactory(), definition);
            }
        }
    }


    private void prepareRefresh() {
        //根据配置装载各个模块
        loadWithConfig();
        //注册Rpc应用处理器进行构建
        registerRpcApplicationProcessor();
        //注册事件发布器
        registerEventPublisher();
        //扫描并配置感知类
        scanAndSetAware();

    }

    private void refreshObjectFactory() {
        getObjectFactory().refresh();
    }


    protected void scanAndSetAware() {
        //内部组件
        setAwareToInternalComponent();
        //rpc应用处理器
        setAwareToRpcApplicationProcessor();
        //各种执行器
        setAwareToRpcInvoker();
    }

    /**
     * 内部组件设置aware
     */
    protected void setAwareToInternalComponent() {
        //RpcNodeDefinitionRegister
        setAwareToObject(getRpcDefinitionRegister());
        //RpcEndpoint
        setAwareToObject(getEndpoint());
        //RpcClient
        setAwareToObject(getClient());
        //RpcNodeRegister
        setAwareToObject(getRpcNodeRegister());
        //ObjectFactory
        setAwareToObject(getObjectFactory());
        //EventPublish
        setAwareToObject(getRpcEventPublisher());
    }


    private void setAwareToRpcApplicationProcessor() {
        for (RpcApplicationProcessor processor : getRegisteredApplicationProcessors()) {
            setAwareToObject(processor);
        }
    }

    private void setAwareToRpcInvoker() {
        for (ConsumeInvoker consumeInvoker : getRegisteredConsumeInvokers()) {
            setAwareToObject(consumeInvoker);
        }

        for (ProvideInvoker provideInvoker : getProvideInvokers()) {
            setAwareToObject(provideInvoker);
        }

        for (RpcClientRequestInterceptor interceptor : getClientRequestInterceptor()) {
            setAwareToObject(interceptor);
        }

        for (RpcEventListener listener : getRpcEventListeners()) {
            setAwareToObject(listener);
        }
    }

    protected void setAwareToObject(Object object) {
        if (!(object instanceof Aware)) {
            return;
        }
        if (object instanceof RpcApplicationContextAware) {
            ((RpcApplicationContextAware) object).setRpcApplicationContext(this);
        }
        if (object instanceof RpcDefinitionRegisterAware) {
            ((RpcDefinitionRegisterAware) object).setRpcDefinitionRegister(getRpcDefinitionRegister());
        }
        if (object instanceof RpcEventPublisherAware) {
            ((RpcEventPublisherAware) object).setRpcEventPublisher(getRpcEventPublisher());
        }
        if (object instanceof RpcObjectFactoryAware) {
            ((RpcObjectFactoryAware) object).setRpcObjectFactory(getObjectFactory());
        }
    }

    protected void registerRpcApplicationProcessor() {
        //得到未注册的处理器
        List<RpcApplicationProcessor> unRegisterProcessor = getUnRegisteredApplicationProcessors();
        //进行分类排序
        List<RpcApplicationProcessor> internalProcessors = new ArrayList<>();
        List<RpcApplicationProcessor> orderedProcessors = new ArrayList<>();
        List<RpcApplicationProcessor> nonOrderedProcessors = new ArrayList<>();
        //主要的处理器
        for (RpcApplicationProcessor processor : unRegisterProcessor) {
            if(processor == null){
                continue;
            }
            if (processor instanceof RpcDefinitionRegisterProcessor) {
                internalProcessors.add(processor);
            } else if (processor instanceof Order) {
                orderedProcessors.add(processor);
            } else {
                nonOrderedProcessors.add(processor);
            }
        }
        //排序
        sortOrderRpcApplicationProcessor(orderedProcessors);
        List<RpcApplicationProcessor> processors = getRegisteredApplicationProcessors();
        processors.clear();
        processors.addAll(internalProcessors);
        processors.addAll(orderedProcessors);
        processors.addAll(nonOrderedProcessors);
    }


    private void sortOrderRpcApplicationProcessor(List<RpcApplicationProcessor> processors) {
        Order.sort(processors);
    }


    protected void invokeRpcApplicationProcessor(RpcApplicationContext context) {
        List<RpcApplicationProcessor> applicationProcessors = getRegisteredApplicationProcessors();
        //execute RpcDefinitionRegisterProcessor
        for (RpcApplicationProcessor processor : applicationProcessors) {
            if(processor instanceof RpcDefinitionRegisterProcessor){
                ((RpcDefinitionRegisterProcessor) processor).registerRpcDefinition(getRpcNameGenerator(),getRpcDefinitionRegister());
            }
        }
        //execute common RpcDefinition
        for (RpcApplicationProcessor processor : applicationProcessors) {
                processor.process(context);
        }
    }


    protected void registerEventPublisher() {
        multicaster.clear();
        scanInternalComponentIfEventListener();
        for (RpcEventListener listener : getRpcEventListeners()) {
            multicaster.addEventListener(listener);
        }
    }


    /**
     * 扫描内部组件是否是事件监听器
     */
    protected void scanInternalComponentIfEventListener() {
        //RpcEndpoint
        addMulticasterIfNeed(getEndpoint());
        //application
        addMulticasterIfNeed(this);
        //RpcDefinitionRegister
        addMulticasterIfNeed(getRpcDefinitionRegister());
        //RpcNodeRegister
        addMulticasterIfNeed(getRpcNodeRegister());
        //rpcClient
        addMulticasterIfNeed(getClient());
        //ObjectFactory
        addMulticasterIfNeed(getObjectFactory());
    }


    private void addMulticasterIfNeed(Object object) {
        if (object instanceof RpcEventListener) {
            multicaster.addEventListener(((RpcEventListener) object));
        }
    }

    protected List<RpcApplicationProcessor> getRegisteredApplicationProcessors() {
        return this.registeredProcessors;
    }

    protected List<ConsumeInvoker> getRegisteredConsumeInvokers() {
        return registeredConsumeInvoke;
    }

    /**
     * 获得Rpc服务注册表提供给下层Client-API生成node
     *
     * @return
     */
    protected List<RpcDefinition> getDefinitions() {
        return Collections.unmodifiableList(definitions);
    }

    /**
     * 生成Rpc服务注册表
     */
    protected void refreshRpcDefinition() {
        definitions.clear();
        definitions.addAll(getRpcDefinitionRegister().getAllDefinitions());
    }




}
